using System;
using System.IO;
using System.Text;
using System.Collections;

using Gtk;

namespace ToolsExample
{
	public class ToolsExample : Window
	{
		private Button parse_button;
		private Button tag_button;
		private Button chunk_button;
		private Button tokenize_button;
		private Button name_find_button;
		private Button split_button;
		
		private TextView output_textview;
		private ScrolledWindow output_textview_window;
		
		private TextView input_textview;
		private ScrolledWindow input_textview_window;
		
		private string models_path;
		
		private OpenNLP.Tools.SentenceDetect.MaximumEntropySentenceDetector sentence_detector;
		private OpenNLP.Tools.Tokenize.EnglishMaximumEntropyTokenizer tokenizer;
		private OpenNLP.Tools.PosTagger.EnglishMaximumEntropyPosTagger tagger;
		private OpenNLP.Tools.Chunker.EnglishTreebankChunker chunker;
		private OpenNLP.Tools.Parser.EnglishTreebankParser parser;
		private OpenNLP.Tools.NameFind.EnglishNameFinder name_finder;
		
		public ToolsExample () : base ("Natural Language Processing Baby")
		{
			models_path = System.IO.Path.Combine (ConfigureDefines.InstallDir, "models");

			parse_button = new Button("Parse");
			tag_button = new Button("Tag");
			chunk_button = new Button("Chunk");
			tokenize_button = new Button("Tokenize");
			name_find_button = new Button("NameFind");
			split_button = new Button("Split");

			output_textview = new TextView (); 
			output_textview.WrapMode = WrapMode.Word;
			input_textview = new TextView ();
			input_textview.WrapMode = WrapMode.Word;

			output_textview_window = new ScrolledWindow ();
			output_textview_window.Child = output_textview;
			input_textview_window = new ScrolledWindow ();
			input_textview_window.Child = input_textview;

			output_textview_window.ShadowType = ShadowType.In;
			output_textview_window.VscrollbarPolicy = PolicyType.Automatic;
			output_textview_window.HscrollbarPolicy = PolicyType.Never;
			input_textview_window.ShadowType = ShadowType.In;
			input_textview_window.VscrollbarPolicy = PolicyType.Automatic;
			input_textview_window.HscrollbarPolicy = PolicyType.Never;

			parse_button.Clicked += new System.EventHandler(parse_button_Clicked);
			tag_button.Clicked += new System.EventHandler(tag_button_Clicked);
			chunk_button.Clicked += new System.EventHandler(chunk_button_Clicked);
			tokenize_button.Clicked += new System.EventHandler(tokenize_button_Clicked);
			name_find_button.Clicked += new System.EventHandler(name_find_button_Clicked);
			split_button.Clicked += new System.EventHandler(split_button_Clicked);

			input_textview.Buffer.Text = "The bus for Islamabad is $5. You better hurry Jack so that you don't miss it!";

			DefaultHeight = 300;
			DefaultWidth = 500;

			VBox vbox = new VBox ();
			vbox.BorderWidth = 5;

			HBox hbox = new HBox ();
			hbox.Add(parse_button);
			hbox.Add(tag_button);
			hbox.Add(chunk_button);
			hbox.Add(tokenize_button);
			hbox.Add(name_find_button);
			hbox.Add(split_button);

			vbox.PackStart(input_textview_window, true, true, 0);
			vbox.PackStart(hbox, false, false, 5);
			vbox.PackStart(output_textview_window, true, true, 0);

			Add(vbox);

			ShowAll ();
		}
		
		static void Main() 
		{
			Application.Init ();
			new ToolsExample ();
			Application.Run ();
		}
		
		private void split_button_Clicked(object sender, System.EventArgs e)
		{		
			string[] sentences = SplitSentences(input_textview.Buffer.Text);
			
			output_textview.Buffer.Text = string.Join("\r\n\r\n", sentences);
		}

		private void tokenize_button_Clicked(object sender, System.EventArgs e)
		{
			StringBuilder output = new StringBuilder();

			string[] sentences = SplitSentences(input_textview.Buffer.Text);

			foreach(string sentence in sentences) {
				string[] tokens = TokenizeSentence(sentence);
				output.Append(string.Join(" | ", tokens)).Append("\r\n\r\n");
			}

			output_textview.Buffer.Text = output.ToString();
		}

		private void tag_button_Clicked(object sender, System.EventArgs e)
		{
			StringBuilder output = new StringBuilder();

			string[] sentences = SplitSentences(input_textview.Buffer.Text);

			foreach(string sentence in sentences) {
				string[] tokens = TokenizeSentence(sentence);
				string[] tags = PosTagTokens(tokens);
				
				for (int currentTag = 0; currentTag < tags.Length; currentTag++)
					output.Append(tokens[currentTag]).Append("/").Append(tags[currentTag]).Append(" ");
				
				output.Append("\r\n\r\n");
			}
			
			output_textview.Buffer.Text = output.ToString();
		}
		
		private void chunk_button_Clicked(object sender, System.EventArgs e)
		{
			StringBuilder output = new StringBuilder();
			
			string[] sentences = SplitSentences(input_textview.Buffer.Text);
			
			foreach(string sentence in sentences) {
				string[] tokens = TokenizeSentence(sentence);
				string[] tags = PosTagTokens(tokens);

				output.Append(ChunkSentence(tokens, tags)).Append("\r\n");
			}

			output_textview.Buffer.Text = output.ToString();
		}

		private void parse_button_Clicked(object sender, System.EventArgs e)
		{
			StringBuilder output = new StringBuilder();

			string[] sentences = SplitSentences(input_textview.Buffer.Text);

			foreach(string sentence in sentences) {
				output.Append(ParseSentence(sentence).Show()).Append("\r\n\r\n");
			}

			output_textview.Buffer.Text = output.ToString();
		}

		private void name_find_button_Clicked(object sender, System.EventArgs e)
		{
			StringBuilder output = new StringBuilder();
			
			string[] sentences = SplitSentences(input_textview.Buffer.Text);
			
			foreach(string sentence in sentences)
				output.Append(FindNames(sentence)).Append("\r\n");
			
			output_textview.Buffer.Text = output.ToString();
		}
		
		private string[] SplitSentences(string paragraph)
		{
			if (sentence_detector == null)
				sentence_detector = new OpenNLP.Tools.SentenceDetect.EnglishMaximumEntropySentenceDetector(System.IO.Path.Combine (models_path, "EnglishSD.nbin"));

			return sentence_detector.SentenceDetect(paragraph);
		}

		private string[] TokenizeSentence(string sentence)
		{
			if (tokenizer == null)
				tokenizer = new OpenNLP.Tools.Tokenize.EnglishMaximumEntropyTokenizer(System.IO.Path.Combine (models_path, "EnglishTok.nbin"));

			return tokenizer.Tokenize(sentence);
		}

		private string[] PosTagTokens(string[] tokens)
		{
			if (tagger == null)
				tagger = new OpenNLP.Tools.PosTagger.EnglishMaximumEntropyPosTagger(System.IO.Path.Combine (models_path, "EnglishPOS.nbin"), 
													System.IO.Path.Combine (System.IO.Path.Combine (models_path, "parser"), "tagdict"));

			return tagger.Tag(tokens);
		}

		private string ChunkSentence(string[] tokens, string[] tags)
		{
			if (chunker == null)
				chunker = new OpenNLP.Tools.Chunker.EnglishTreebankChunker(System.IO.Path.Combine (models_path, "EnglishChunk.nbin"));
			
			return chunker.GetChunks(tokens, tags);
		}

		private OpenNLP.Tools.Parser.Parse ParseSentence(string sentence)
		{
			if (parser == null)
				parser = new OpenNLP.Tools.Parser.EnglishTreebankParser(models_path, true, false);

			return parser.DoParse(sentence);
		}

		private string FindNames(string sentence)
		{
			if (name_finder == null)
				name_finder = new OpenNLP.Tools.NameFind.EnglishNameFinder(System.IO.Path.Combine (models_path, "namefind"));

			string[] models = new string[] {"date", "location", "money", "organization", "percentage", "person", "time"};
			return name_finder.GetNames(models, sentence);
		}
	}
}
